﻿using ALEXBlog.Common.JsonHelper;
using ALEXBlog.IRepository.Redis;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ALEXBlog.Repository.Redis
{
    public class RedisRepository : IRedisRepository
    {
        readonly IConnectionMultiplexer redisContext;
        readonly IDatabase database;
        //readonly ILogger<RedisRepository> logger;
        public RedisRepository(RedisConfigurationOprions _redisConfig = null)
        {
            redisContext = ConnectionMultiplexer.Connect(GetConfiguraOptions(_redisConfig));
            database = redisContext.GetDatabase();
        }

        /// <summary>
        /// 读取Appsttings
        /// </summary>
        /// <param name="_redisConfig"></param>
        /// <returns></returns>
        ConfigurationOptions GetConfiguraOptions(RedisConfigurationOprions _redisConfig = null)
        {
            _redisConfig = _redisConfig ?? new RedisConfigurationOprions()
            {
                EndPoints = Appsettings.GetAppsettingsValue("AppSettings", "RedisCaching", "ConnectionString").Split(','),
                KeepAlive = int.Parse(Appsettings.GetAppsettingsValue("AppSettings", "RedisCaching", "KeepAlive")),
                PassWord = Appsettings.GetAppsettingsValue("AppSettings", "RedisCaching", "PassWord")
            };
            return _redisConfig.configurationOptions;

        }

        /// <summary>
        /// 获取Redis服务
        /// </summary>
        /// <returns></returns>
        public IServer GetServer()
        {
            return redisContext.GetServer(redisContext.GetEndPoints().First());
        }

        /// <summary>
        /// 获取RedisDatabaseContext
        /// </summary>
        /// <returns></returns>
        public IDatabase GetDatabase() => database;

        /// <summary>
        /// 清空所有键值
        /// </summary>
        /// <returns></returns>
        public async Task ClearAsync()
        {
            await GetServer().FlushDatabaseAsync();
        }

        /// <summary>
        /// 键是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<bool> ExistAsync(string key)
        {
            return await database.KeyExistsAsync(key);
        }

        /// <summary>
        /// 设置键值对(序列化为Json)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="Value"></param>
        /// <param name="cacheTime"></param>
        /// <returns></returns>
        public async Task<bool> SetAsync<TEntity>(string key, TEntity value, TimeSpan cacheTime)
        {
            return await database.StringSetAsync(key, Serialize.Serializeing(value), cacheTime);
        }

        /// <summary>
        /// 设置键值对
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<bool> SetAsync(string key, string value)
        {
            return await database.StringSetAsync(key, value);
        }

        /// <summary>
        /// 设置键值对
        /// </summary>
        /// <param name="key"></param>
        /// <param name="Value"></param>
        /// <param name="cacheTime"></param>
        /// <returns></returns>
        public async Task<bool> SetAsync(string key, string value, TimeSpan cacheTime)
        {
            if (string.IsNullOrEmpty(value))
            {
                return await database.StringSetAsync(key, value, cacheTime);
            }
            return false;
        }

        /// <summary>
        /// 删除键值对
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<bool> RemoveAsync(string key)
        {
            return await database.KeyDeleteAsync(key);
        }

        /// <summary>
        /// 删除键值对
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> RemoveAsync(params string[] keys)
        {
            return await database.KeyDeleteAsync(keys.Select(item => (RedisKey)item).ToArray());
        }


        /// <summary>
        /// 根据键获取值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<TEntity> GetAsync<TEntity>(string key)
        {
            var value = await database.StringGetAsync(key);
            return Serialize.Deserializeing<TEntity>(value);

        }

        /// <summary>
        /// 根据键获取值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<string> GetAsync(string key)
        {
            return await database.StringGetAsync(key);
        }

        /// <summary>
        /// 往链表头部添加值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListFirstPushAsync<TEntity>(string redisKey, params TEntity[] redisValue)
        {
            var redisByteArray = redisValue.Select(x => (RedisValue)Serialize.Serializeing(x));
            return await database.ListLeftPushAsync(redisKey, redisByteArray.ToArray());
        }

        /// <summary>
        /// 往链表尾部添加值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListLastPushAsync<TEntity>(string redisKey, params TEntity[] redisValue)
        {
            var redisByteArray = redisValue.Select(x => (RedisValue)Serialize.Serializeing(x));
            return await database.ListRightPushAsync(redisKey, redisByteArray.ToArray());
        }

        /// <summary>
        /// 移除链表头部的第一个值,并返回移除的值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<TEntity> ListFirstRemoveAsync<TEntity>(string key)
        {
            return Serialize.Deserializeing<TEntity>(await database.ListLeftPopAsync(key));
        }
        /// <summary>
        /// 移除链表头部的第一个值,并返回移除的值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<string> ListFirstRemoveAsync(string key)
        {
            return await database.ListLeftPopAsync(key);
        }
        /// <summary>
        /// 移除链表尾部的第一个值,并返回移除的值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<TEntity> ListLastRemoveAsync<TEntity>(string key)
        {
            return Serialize.Deserializeing<TEntity>(await database.ListRightPopAsync(key));
        }

        /// <summary>
        /// 移除链表尾部的第一个值,并返回移除的值
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<string> ListLastRemoveAsync(string key)
        {
            return await database.ListRightPopAsync(key);
        }
        /// <summary>
        /// 返回链表长度
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> ListLengthAsync(string key)
        {
            return await database.ListLengthAsync(key);
        }

        /// <summary>
        /// 返回整个链表
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> ListGetAsync<TEntity>(string key)
        {
            var listArray = await database.ListRangeAsync(key);
            return listArray.Select(x => Serialize.Deserializeing<TEntity>(x));
        }
        /// <summary>
        /// 返回整个链表
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> ListRangeGetAsync(string key)
        {
            var listArray = await database.ListRangeAsync(key);
            return listArray.Select(x => (string)x);
        }

        /// <summary>
        /// 返回链表子集
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> ListRangeGetAsync<TEntity>(string key, int startIndex, int stopIndex)
        {
            var valueList = await database.ListRangeAsync(key, startIndex, stopIndex);
            return valueList.Select(x => Serialize.Deserializeing<TEntity>(x));
        }
        /// <summary>
        /// 返回链表子集
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> ListRangeGetAsync(string key, int startIndex, int stopIndex)
        {
            var valueList = await database.ListRangeAsync(key, startIndex, stopIndex);
            return valueList.Select(x => (string)x);
        }

        /// <summary>
        /// 删除链表中与输入值对应的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="type"> >0:从表头开始向表尾搜索，< 0:从表尾开始向表头搜索，=0:移除表中所有与 VALUE 相等的值</param>
        /// <returns></returns>
        public async Task<long> ListRangeRemoveAsync(string key, string value, long type = 0)
        {
            return await database.ListRemoveAsync(key, value, type);
        }

        /// <summary>
        /// 清空链表
        /// </summary>
        /// <param name="key"></param>
        /// <param name="Value"></param>
        /// <param name="cacheTime"></param>
        /// <returns></returns>
        public async Task ListClearAsync(string key)
        {
            await database.ListTrimAsync(key, 1, 0);
        }


    }
}
